package com.ikingtech.platform.business.message.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ikingtech.framework.sdk.base.model.BatchParam;
import com.ikingtech.framework.sdk.base.model.PageResult;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.core.response.R;
import com.ikingtech.framework.sdk.enums.message.MessageReadStatusEnum;
import com.ikingtech.framework.sdk.message.api.MessageManagementApi;
import com.ikingtech.framework.sdk.message.model.MessageDTO;
import com.ikingtech.framework.sdk.message.model.MessageQueryParamDTO;
import com.ikingtech.framework.sdk.message.model.rpc.MessageSendParam;
import com.ikingtech.framework.sdk.user.api.UserApi;
import com.ikingtech.framework.sdk.user.model.UserBasicDTO;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.framework.sdk.web.annotation.ApiController;
import com.ikingtech.platform.business.message.entity.MessageDO;
import com.ikingtech.platform.business.message.exception.MessageExceptionInfo;
import com.ikingtech.platform.business.message.service.MessageService;
import com.ikingtech.platform.business.message.service.repository.MessageRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
@ApiController(value = "/message/management", name = "消息中心-消息管理", description = "消息中心-消息管理")
public class MessageManagementController implements MessageManagementApi {

    private final MessageRepository repo;

    private final MessageService service;

    private final UserApi userApi;

    /**
     * 分页查询消息列表
     * @param queryParam 查询参数
     * @return 返回消息列表
     */
    @Override
    public R<List<MessageDTO>> page(MessageQueryParamDTO queryParam) {
        // 调用服务层获取消息列表
        PageResult<MessageDO> entities = PageResult.build(this.repo.page(new Page<>(queryParam.getPage(), queryParam.getRows()), Wrappers.<MessageDO>lambdaQuery()
                .eq(Tools.Str.isNotBlank(queryParam.getBusinessKey()), MessageDO::getBusinessKey, queryParam.getBusinessKey())
                .in(Tools.Coll.isNotBlank(queryParam.getBusinessKeys()), MessageDO::getBusinessKey, queryParam.getBusinessKeys())
                .like(Tools.Str.isNotBlank(queryParam.getMessageContent()), MessageDO::getMessageContent, queryParam.getMessageContent())
                .eq(Tools.Str.isNotBlank(queryParam.getDeliverStatus()), MessageDO::getDeliverStatus, queryParam.getDeliverStatus())
                .eq(Tools.Str.isNotBlank(queryParam.getChannel()), MessageDO::getChannel, queryParam.getChannel())
                .eq(Tools.Str.isNotBlank(queryParam.getReadStatus()), MessageDO::getReadStatus, queryParam.getReadStatus())
                .eq(Tools.Str.isNotBlank(queryParam.getReceiverId()), MessageDO::getReceiverId, queryParam.getReceiverId())
                .eq(MessageDO::getTenantCode, Me.tenantCode())
                .orderByDesc(MessageDO::getCreateTime)));

        // 调用用户API获取用户基本信息
        List<UserBasicDTO> users = this.userApi.listInfoByIds(BatchParam.build(Tools.Coll.convertList(entities.getData(), MessageDO::getReceiverId))).getData();

        // 将用户信息转换为Map
        Map<String, UserBasicDTO> userMap = Tools.Coll.convertMap(users, UserBasicDTO::getId);

        // 将消息列表转换为MessageDTO列表
        return R.ok(entities.getPages(), entities.getTotal(), Tools.Coll.convertList(entities.getData(), entity -> {
            MessageDTO message = Tools.Bean.copy(entity, MessageDTO.class);

            // 设置渠道名称
            if (null != message.getChannel()) {
                message.setChannelName(message.getChannel().description);
            }

            // 设置送达状态名称
            if (null != message.getDeliverStatus()) {
                message.setDeliverStatusName(message.getDeliverStatus().description);
            }

            // 设置已读状态名称
            if (null != message.getReadStatus()) {
                message.setReadStatusName(message.getReadStatus().description);
            }

            // 设置送达状态名称
            if (null != message.getDeliverStatus()) {
                message.setDeliverStatusName(message.getDeliverStatus().description);
            }

            // 设置接收者名称
            if (userMap.containsKey(entity.getReceiverId())) {
                message.setReceiverName(userMap.get(entity.getReceiverId()).getName());
            }

            return message;
        }));
    }

    /**
     * 根据id读取消息
     * @param id 消息id
     * @return 返回读取消息的结果
     */
    @Override
    public R<Object> readById(String id) {
        // 获取消息实体
        MessageDO entity = this.repo.getById(id);
        // 如果消息实体为空，则抛出异常
        if (null == entity) {
            throw new FrameworkException(MessageExceptionInfo.MESSAGE_NOT_FOUND);
        }
        // 设置消息已读状态和时间
        entity.setReadStatus(MessageReadStatusEnum.READ.name());
        entity.setReadTime(LocalDateTime.now());
        // 更新消息实体
        this.repo.updateById(entity);
        // 返回读取消息的结果
        return R.ok();
    }

    /**
     * 读取消息列表
     * @return 返回操作结果
     */
    @Override
    public R<Object> readAll() {
        // 获取未读消息列表
        List<MessageDO> entities = this.repo.list(Wrappers.<MessageDO>lambdaQuery().eq(MessageDO::getReadStatus, MessageReadStatusEnum.NO_READ).eq(MessageDO::getReceiverId, Me.id()));
        // 更新消息列表的读状态和读取时间
        this.repo.updateBatchById(Tools.Coll.traverse(entities, entity -> {
            entity.setReadStatus(MessageReadStatusEnum.READ.name());
            entity.setReadTime(LocalDateTime.now());
            return entity;
        }));
        // 返回操作结果
        return R.ok();
    }

    /**
     * 发送消息
     *
     * @param sendParam 消息发送参数
     * @return 操作结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Object> send(MessageSendParam sendParam) {
        // 调用发送消息
        this.service.send(sendParam);
        // 返回操作结果
        return R.ok();
    }
}
